local Obj = require("core.Obj")
local ObjHuman = require("core.ObjHuman")
local RoleExcel = require("excel.Role")
local RoleDefine = require("role.RoleDefine")
local CombatCalc = require("skill.CombatCalc")
local Buffer = require("buffer.Buffer")
local Equip = require("bag.Equip")
local EquipScore = require("excel.Equip").equipScore
local attrInitValue = RoleExcel.baseAttrInitValue[1]
local Horse = require("horse.HorseLogic")
local VipLogic = require("vip.VipLogic")
local Msg = require("core.Msg")
local ShenbingLogic = require("shenbing.ShenbingLogic")
local FamilyLogicFL = require("family.FamilyLogicFL")
local ItemLogic = require("bag.ItemLogic")
local PetLogic = require("pet.PetLogic")
local AcvityDefine = require("activity.Define")
local RankDefine = require("rank.RankDefine")
local HorseLogic = require("horse.HorseLogic")
local BaowuLogic = require("baowu.BaowuLogic")
local ArmourLogicFL = require("armour.ArmourLogicFL")
local QiliaoLogic = require("qiliao.QiliaoLogic")
local TitleLogic = require("title.TitleLogic")
local OfficialLogic = require("official.OfficialLogic")

local math = _G.math

--角色最高等级
ROLE_MAX_LV = nil

function init()
    ROLE_MAX_LV = #RoleExcel.exp
end

function doCalc(human)
    if ObjHuman.onlineUuid[human._id] then
        Buffer.calcsInit(human)
    end

    human.attr = human.attr or {}
    for k in pairs(human.attr) do
        human.attr[k] = nil
    end

    local attr = human.attr
    local attrExcel = RoleExcel.baseAttr[human.db.lv]
    local expExcel = RoleExcel.exp

    -- init value
    for key = RoleDefine.ATK , RoleDefine.ALL_GEM_ATTR do
        attr[key] = 0
    end
    
    for key = RoleDefine.HORSE_LEVEL_ATTR_UP_RATE , RoleDefine.PET_DAMANGE_RATE do
        attr[key] = 0
    end
    
    for key = RoleDefine.SKILL_ATTR_1 , RoleDefine.SKILL_ATTR_20 do
        attr[key] = 0
    end
    
    --配置
    attr[RoleDefine.LEVEL] = human.db.lv
    attr[RoleDefine.HP_MAX] = attrExcel.hp_max
    attr[RoleDefine.MP_MAX] = attrExcel.mp_max
    attr[RoleDefine.HIT] = attrExcel.hit
    attr[RoleDefine.SHANBI] = attrExcel.shanbi
    attr[RoleDefine.BAOJI] = attrExcel.baoji
    attr[RoleDefine.RENXING] = attrExcel.renxing
    attr[RoleDefine.GEDANG] =attrExcel.gedang
    attr[RoleDefine.ATK]  = attrExcel.atk
    attr[RoleDefine.DEF]  = attrExcel.def
    attr[RoleDefine.GEDANG_RATE] = attrInitValue.gedang_rate
    attr[RoleDefine.HP_RATE] = attrInitValue.hp_rate
    attr[RoleDefine.MP_RECOVER] = attrInitValue.mp_recover
    attr[RoleDefine.SPEED] = attrInitValue.speed
    
    --默认0
    attr[RoleDefine.BAOJI_UP] = 0
    attr[RoleDefine.BAOJI_DOWN] = 0
    attr[RoleDefine.ATK_YAZHI] = 0
    attr[RoleDefine.DEF_YAZHI] = 0
    attr[RoleDefine.HUJIA_CT] = 0
    attr[RoleDefine.DIKANG_CT] = 0
    attr[RoleDefine.MONSTER_KX] = 0
    attr[RoleDefine.MENGJIANG_KX] =0
    attr[RoleDefine.SHENMOU_KX] = 0
    attr[RoleDefine.XUNYING_KX] = 0
    attr[RoleDefine.MAKE_SHANGHAI_RATE] = 0
    attr[RoleDefine.RECV_SHANGHAI_RATE] = 0

    -- 属性
    attr[RoleDefine.ATTR_HIT_RATE] = 0			--攻击方命中几率
    attr[RoleDefine.ATTR_BAO_JI_RATE] = 0		--攻击方暴击几率
    attr[RoleDefine.ATTR_DODGE_RATE] = 0		--防守方闪避几率
    attr[RoleDefine.ATTR_DEF_REN_XING_RATE] = 0	--防守方韧性几率

    attr[RoleDefine.HUIXIN_RATE] = attrInitValue.huixin  --会心一击
    attr[RoleDefine.ZHUOYUE_RATE]= attrInitValue.zhuoyue  --卓越一击
    attr[RoleDefine.MULTI_BAOJI_RATE] = attrInitValue.doublebaoji --双倍暴击
    attr[RoleDefine.FENG_ATK]        = 0     --风属性伤害
    attr[RoleDefine.FENG_KX]          = 0     --风属性抗性
    attr[RoleDefine.FIRE_ATK]        = 0     --火属性伤害
    attr[RoleDefine.FIRE_KX]          = 0     --火属性抗性
    attr[RoleDefine.WATER_ATK]       = 0     --水属性伤害
    attr[RoleDefine.WATER_KX ]        = 0     --水属性抗性
    attr[RoleDefine.LEI_ATK]         = 0     --雷属性伤害
    attr[RoleDefine.LEI_KX]           = 0     --雷属性抗性


    -- 显示用
    attr[RoleDefine.HIT_RATE] = 0			--攻击方命中几率
    attr[RoleDefine.BAO_JI_RATE] = 0		--攻击方暴击几率
    attr[RoleDefine.DODGE_RATE] = 0			--防守方闪避几率
    attr[RoleDefine.DEF_REN_XING_RATE] = 0	--防守方韧性几率

    attr[RoleDefine.HP] = human.db.hp    --当前生命值
    attr[RoleDefine.MP] = human.db.mp    --当前魔法值
    attr[RoleDefine.EXP] = human.db.exp  --当前经验值
    attr[RoleDefine.EXP_MAX] = expExcel[human.db.lv].exp --最大经验值
    attr[RoleDefine.SPEED_RATE] = 0
    attr[RoleDefine.TOTAL_EQUIP_POWER] = 0

    --二级货币
    attr[RoleDefine.YINLIANG] = human.db.yinliang
    attr[RoleDefine.BIND_YUANBAO] = human.db.bind_yuanbao
    attr[RoleDefine.YUANBAO] = human.db.yuanbao
    attr[RoleDefine.ZHANGONG] = human.db.zhangong
    attr[RoleDefine.AWAKE_VALUE] = human.db.awakeVal
    attr[RoleDefine.WUSHUANG] = human.db.wushuang
    attr[RoleDefine.PRESTIGE] = human.db.prestige
    attr[RoleDefine.PRESTIGE_MAX] = 10000
    attr[RoleDefine.PRESTIGE_HISTORY] = human.db.prestigeHistory
    attr[RoleDefine.RONGYU]  = human.db.rongyu
    attr[RoleDefine.ZHANGONG_MAX] = RoleExcel.baseAttr[human.db.lv] and RoleExcel.baseAttr[human.db.lv].maxZhangong or RoleExcel.baseAttr[150].maxZhangong
    attr[RoleDefine.ZHANGONG_HISTORY] = human.db.zhangongHistory
    attr[RoleDefine.MAX_AWAKE_VALUE] = 1000
    attr[RoleDefine.JUMP_VALUE] = human.db.jumpValue
    attr[RoleDefine.JUMP_VALUE_MAX] = attrInitValue.jump_max
    attr[RoleDefine.HISTORY_CHONGZHI] = human.db.historyYuanbao
    attr[RoleDefine.VIP_LEVEL] = VipLogic.getVipLv(human)
    attr[RoleDefine.SHENBING_ID] = human.db.putonShenbing
    attr[RoleDefine.DAILY_CHONGZHI] = human.db.dailyChongzhi
    attr[RoleDefine.DAILY_COST_YUANBAO] = human.db.dailyCostYuanbao
    --属性加到人物身上
    Equip.doCalc(human)  --装备属性
    human.attr[RoleDefine.TOTAL_EQUIP_POWER] = ObjHuman.getEquipTotalPower(human)

    Horse.doCalc(human)  --坐骑属性
    ShenbingLogic.doCalc(human)  --神兵属性
    FamilyLogicFL.doCalc(human) --军团旗帜与韬略属性加成
    ItemLogic.doAttrAddAttr(human) -- 属性果实永久加成
    PetLogic.addAllRA(human, true) --神将属性加成
    BaowuLogic.doCalc(human)  --宝物属性加成
    ArmourLogicFL.doCalc(human)  --宝物属性加成
    TitleLogic.doCalc(human) -- 称号属性加成
    OfficialLogic.doCalc(human) --军衔属性加成

    -- 为了战斗力不计算Buff，先计算一遍
    local oldSpeed = attr[RoleDefine.SPEED]
    local oldAtk = attr[RoleDefine.ATK]
    local oldDef = attr[RoleDefine.DEF]
    local oldHpMax= attr[RoleDefine.HP_MAX]
    local oldHp = attr[RoleDefine.HP]
    local oldMp = attr[RoleDefine.MP]
    attr[RoleDefine.SPEED] = attr[RoleDefine.SPEED] * (1 + attr[RoleDefine.SPEED_RATE])
    attr[RoleDefine.ATK] = attr[RoleDefine.ATK] * (1 + attr[RoleDefine.ATK_RATE])
    attr[RoleDefine.DEF] = attr[RoleDefine.DEF] * (1 + attr[RoleDefine.DEF_RATE])
    attr[RoleDefine.HP_MAX] = attr[RoleDefine.HP_MAX] * (1 + attr[RoleDefine.HP_MAX_RATE])
    CombatCalc.calcAttr(human)
    if human.db.hp > attr[RoleDefine.HP_MAX] then
        human.db.hp = human.attr[RoleDefine.HP_MAX]
    end
    if human.db.mp > attr[RoleDefine.MP_MAX] then
        human.db.mp = human.attr[RoleDefine.MP_MAX]
    end
    human.attr[RoleDefine.HP] = human.db.hp
    human.attr[RoleDefine.MP] = human.db.mp
    local oldPower = human.db.zhandouli
    human.db.zhandouli = calHumanPower(human.attr) + ShenbingLogic.getSkillZhandouli(human, human.db.putonShenbing) + HorseLogic.getSkillZhandouli(human, human.db.chooseHorseId) + BaowuLogic.getBaowuSkillPower(human, true)
                      + PetLogic.skillZhandouli(human) + QiliaoLogic.getQiliaoPower(human)
    if oldPower ~= human.db.zhandouli then
        local sendMsg = Msg.lw.LW_CHECK_RANK_CHANGE
        sendMsg.type = RankDefine.POWER_RANK_TYPE
        sendMsg.otherInfo = 0
        Msg.send2world(sendMsg, human._id)
    end
    human.attr[RoleDefine.ZHANDOULI] = human.db.zhandouli
    attr[RoleDefine.SPEED] = oldSpeed
    attr[RoleDefine.ATK] = oldAtk
    attr[RoleDefine.DEF] = oldDef
    attr[RoleDefine.HP_MAX] = oldHpMax
    human.db.hp = oldHp
    human.db.mp = oldMp

    -- 加buff属性
    if ObjHuman.onlineUuid[human._id] then
        Buffer.refreshRate(human)
    end
    -- rate attr
    attr[RoleDefine.SPEED] = attr[RoleDefine.SPEED] * (1 + attr[RoleDefine.SPEED_RATE])
    attr[RoleDefine.ATK] = attr[RoleDefine.ATK] * (1 + attr[RoleDefine.ATK_RATE])
    attr[RoleDefine.DEF] = attr[RoleDefine.DEF] * (1 + attr[RoleDefine.DEF_RATE])
    attr[RoleDefine.HP_MAX] = attr[RoleDefine.HP_MAX] * (1 + attr[RoleDefine.HP_MAX_RATE])

    if human.id then
        Obj.setSpeed(human, attr[RoleDefine.SPEED])
        attr[RoleDefine.SPEED] = human.speed
    end

    if ObjHuman.onlineUuid[human._id] then
        Buffer.refresh(human)
    end


    -- 其他属性客户端显示中间值（非有效值）(附加说明:战斗计算需要)
    CombatCalc.calcAttr(human)

    if attr[RoleDefine.HP_MAX] < 1 or attr[RoleDefine.MP_MAX] < 1  then
        assert()
    end

    attr[RoleDefine.HP_MAX] = math.floor(attr[RoleDefine.HP_MAX])
    attr[RoleDefine.MP_MAX] = math.floor(attr[RoleDefine.MP_MAX])
    if human.db.hp > attr[RoleDefine.HP_MAX] then
        human.db.hp = human.attr[RoleDefine.HP_MAX]
    end
    if human.db.mp > attr[RoleDefine.MP_MAX] then
        human.db.mp = human.attr[RoleDefine.MP_MAX]
    end

    -- set hp mp
    ObjHuman.setHp(human, human.db.hp, true)		-- 为了防止hp最大值变化下 导致的hp超过hpmax
    ObjHuman.setMp(human, human.db.mp, true)		-- 为了防止mp最大值变化下 导致的mp超过mpmax
    attr[RoleDefine.HP] = human.db.hp
    attr[RoleDefine.MP] = human.db.mp
    
    --全属性分配
    attr[RoleDefine.FENG_ATK] = attr[RoleDefine.FENG_ATK]+attr[RoleDefine.ALL_ATTR_ATK]
    attr[RoleDefine.FIRE_ATK] = attr[RoleDefine.FIRE_ATK]+attr[RoleDefine.ALL_ATTR_ATK]
    attr[RoleDefine.WATER_ATK]= attr[RoleDefine.WATER_ATK]+attr[RoleDefine.ALL_ATTR_ATK]
    attr[RoleDefine.LEI_ATK]  = attr[RoleDefine.LEI_ATK]+attr[RoleDefine.ALL_ATTR_ATK]
    attr[RoleDefine.FENG_KX]  = attr[RoleDefine.FENG_KX]+attr[RoleDefine.ALL_ATTR_KX]
    attr[RoleDefine.FIRE_KX]  = attr[RoleDefine.FIRE_KX]+attr[RoleDefine.ALL_ATTR_KX]
    attr[RoleDefine.WATER_KX] = attr[RoleDefine.WATER_KX]+attr[RoleDefine.ALL_ATTR_KX]
    attr[RoleDefine.LEI_KX]   = attr[RoleDefine.LEI_KX]+attr[RoleDefine.ALL_ATTR_KX]
end


function getScore(key)
    return EquipScore[key] and EquipScore[key].score or 0
end


function calHumanPower(attrs)
    local power = 0
    for k, v in pairs(attrs) do
        power = power + getScore(k) * v
    end
    return power
end

function calPowerProto(attrs)
  local power = 0
   if attrs[0] == 0 then
    return power 
  end
  for i=1, attrs[0] do
    power = power + getScore(attrs[i].key) * attrs[i].value 
  end
  return power
end

--属性累加,attr是配置表中的数据
function addAttrs(attrs, attr)
  if not attrs[0] then
    attrs[0] = 0
  end
  for i=1, #attr do
    local isHave = false
    for j=1, attrs[0] do
      if attrs[j].key == attr[i][1] then
        isHave = true
        attrs[j].value = attrs[j].value + attr[i][2]
      end
    end
    if not isHave then      
      if attrs[attrs[0] + 1] then
        attrs[0] = attrs[0] + 1
		attrs[attrs[0]].key = attr[i][1]
		attrs[attrs[0]].value = attr[i][2]
      end
    end
  end
end
--属性累加2，attr是协议中的属性
function addAttrs2(attrs, attr)
  for i=1, attr[0] do
    local isHave = false
    for j=1, attrs[0] do
      if attrs[j].key == attr[i].key then
        isHave = true
        attrs[j].value = attrs[j].value + attr[i].value
      end
    end
    if not isHave then
      attrs[0] = attrs[0] + 1
      attrs[attrs[0]].key = attr[i].key
      attrs[attrs[0]].value = attr[i].value
    end
  end
end
--单个属性累加 
function addOneAttr(attrs, attrOne)
  if not attrs[0] then
    attrs[0] = 0
  end
  for i=1, attrs[0] do
    if attrOne[1] == attrs[i].key then
      attrs[i].value = attrs[i].value + attrOne[2]
      return
    end
  end
  attrs[0] = attrs[0] + 1
  if not attrs[attrs[0] ] then
    attrs[attrs[0] ] = {}
  end
  attrs[attrs[0] ].key = attrOne[1]
  attrs[attrs[0] ].value = attrOne[2]
end
